﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HA.ModFlow.Infrastructure;

using System.Runtime.Serialization;


namespace HA.Data
{
    /// <summary>
    /// 存储modflow的结果数据
    /// 注意：此类不要轻易添加删除字段属性，如果要修改，需要修改就算结果的拷贝操作，在Data2Commands 中
    /// </summary>
    [Serializable]
    public class DSModflow : DSGrid3dCollecion
    {


        public DSModflow()
            : base("ModflowResult")
        {


        }
        public DSModflow(string id)
            : base(id)
        { 
        
        }


        #region 事件模型

        [field:NonSerialized]
        public event EventHandler VectorDataChanged;


        #endregion

        #region 字段属性

        List<HA.ModFlow.Domain.DomainLayer.MFTimeStepLabel> mfTimeStepLabel;
        /// <summary>
        /// 存储各个应力期的逝去时间
        /// </summary>
        public List<HA.ModFlow.Domain.DomainLayer.MFTimeStepLabel> MfTimeStepLabel
        {
            get { return mfTimeStepLabel; }
            set { mfTimeStepLabel = value; }
        }



        List<List<int[,]>> _timeStepIBound = new List<List<int[,]>>();
        /// <summary>
        /// 存储各个应力期的IBound，最外层List的个数应该和上述逝去时间的List个数应该一致的
        /// </summary>
        public List<List<int[,]>> TimeStepIBound
        {
            get { return this._timeStepIBound; }
            set { this._timeStepIBound = value; }
        }




        List<HA.ModFlow.Domain.DomainLayer.BudData> _ccfData;


        /// <summary>
        /// CCF数据
        /// </summary>
        public List<HA.ModFlow.Domain.DomainLayer.BudData> CcfData
        {
            get { return _ccfData; }
            set { _ccfData = value; }
        }


        //FlowVector[, ,] _vectors;

        ///// <summary>
        ///// 用于保存对应的单段 矢量数据
        ///// </summary>
        //public FlowVector[, ,] Vectors
        //{
        //    get { return _vectors; }
        //    set { _vectors = value; }
        //}

        //double[, ,] _ccf_Mag;

        //public double[, ,] CCF_Mag
        //{
        //    get { return _ccf_Mag; }
        //    set { _ccf_Mag = value; }
        //}



        DSVectorGrid3d _vectorGridData;


        /// <summary>
        /// 用于保存对应的所有的矢量数据
        /// </summary>
        public DSVectorGrid3d VectorGridData
        {
            get { return _vectorGridData; }
            set {
                
                
                _vectorGridData = value;

                if (VectorDataChanged!=null)
                {
                    this.VectorDataChanged(this,new EventArgs ());
                    
                }
            
            
            }
        }


        #endregion


        #region 方法

        /// <summary>
        /// 将对应的值改为dataset模式显示
        /// </summary>
        public void CCFToDataSet()
       
        {
            try
            {


                if (this._ccfData == null)
                {

                }

                foreach (HA.ModFlow.Domain.DomainLayer.BudData budData in this._ccfData)
                {
                    if (budData.Id == "lpf" || budData.Id == "bcf")
                    {
                        List<string> strs = new List<string>();

                        foreach (HA.ModFlow.Domain.DomainLayer.BudFile budfile in budData.Datas)
                        {
                            string str = "";
                            foreach (char c in budfile.TEXT)
                            {
                                str += c;
                            }
                            if (strs.Contains(str) == false)
                            {
                                strs.Add(str);
                            }
                        }

                        //个数也有可能不为4个

                        //if (strs.Count != 4)
                        //{
                        //    //错了
                        //}

                        for (int i = 0; i < strs.Count; i++)
                        {
                            List<CellCenterDataSet3d> cells = new List<CellCenterDataSet3d>();

                            for (int j = 0; j < budData.Datas.Count; j++)
                            {
                                string str = "";
                                foreach (char c in budData.Datas[j].TEXT)
                                {
                                    str += c;
                                }

                                if (strs[i] == str)
                                {
                                    cells.Add(budData.Datas[j].Data);

                                }
                            }

                            DSGrid3d dsgrid = new DSGrid3d(strs[i], cells);
                            string name = strs[i].Trim();

                            dsgrid.Name = name;

                            //。。。。。。小李   2011.10.24
                            this.SetCCFToDataSetEllapseTime(dsgrid ,mfTimeStepLabel );



                            this.Add(dsgrid);
                        }

                        continue;
                    }

                    List<CellCenterDataSet3d> cellDatas = new List<CellCenterDataSet3d>();

                    foreach (HA.ModFlow.Domain.DomainLayer.BudFile budFile in budData.Datas)
                    {
                        cellDatas.Add(budFile.Data);
                    }

                    DSGrid3d ds = new DSGrid3d(budData.Id, cellDatas);
                    ds.Name = budData.Name;


                    //。。。。。。小李   2011.10.24
                    this.SetCCFToDataSetEllapseTime(ds, mfTimeStepLabel);


                    //调用add 

                    this.Add(ds);

                    //this.Collecion.Add(ds);

                }

            }
            catch
            {
                System.Windows.MessageBox.Show("抱歉，计算过程出错！请尝试重新计算！");

            }
        }


        /// <summary>
        /// 计算流动均衡,刘
        /// </summary>
        public List <FlowBudget> CalFlowBudget(int index)
        {
            if (this._ccfData == null)
            {
                //出错
                return null;
            }

            List<FlowBudget> result = new List<FlowBudget>();

            double totalFlowIn = 0;
            double totalFlowOut = 0;

            for (int i = 0; i < this._ccfData.Count; i++)
            {
                //如果需求超出范围
                if (index >= this._ccfData[i].Datas.Count || index < 0)
                {
                    //出错了
                }


                double flowIn = 0;
                double flowOut = 0;

                if (this._ccfData[i].Id == "lpf" || this._ccfData[i].Id == "bcf")  //特殊情况的两种文件
                {                    
                    List<string> strs = new List<string>();

                    foreach (HA.ModFlow.Domain.DomainLayer.BudFile budfile in this._ccfData[i].Datas)
                    {
                        string str = "";
                        foreach (char c in budfile.TEXT)
                        {
                            str += c;
                        }
                        if (strs.Contains(str) == false)
                        {
                            strs.Add(str);
                        }
                    }

                    for (int j = 0; j < strs.Count; j++)
                    {
                        flowIn = 0;
                        flowOut = 0;

                        foreach (double value in this._ccfData[i].Datas[strs.Count*index+ j ].Data.Datas)
                        {
                            if (value > 0)
                            {
                                flowIn += value;                               
                            }
                            if (value < 0)
                            {
                                flowOut += value;
                            }
                        }

                        totalFlowIn += flowIn;
                        totalFlowOut += flowOut;

                        string name = strs[j];
                        //foreach (char c in this._ccfData[i].Datas[this._ccfData[i].Datas.Count / strs.Count * j + index].TEXT)
                        //{
                        //    name += c;
                        //}
                        FlowBudget bud = new FlowBudget(name.Trim(), flowIn.ToString(), flowOut.ToString());
                        result.Add(bud);
                    }
                }
                else
                {
                    foreach (double value in this._ccfData[i].Datas[index].Data.Datas)
                    {
                        if (value > 0)
                        {
                            flowIn += value;
                        }
                        if (value < 0)
                        {
                            flowOut += value;
                        }
                    }

                    totalFlowIn += flowIn;
                    totalFlowOut += flowOut;

                    FlowBudget bud = new FlowBudget(this._ccfData[i].Name.Trim(), flowIn.ToString(), flowOut.ToString());

                    result.Add(bud);
                }


            }

            result.Add(new FlowBudget("总流量", totalFlowIn.ToString(), totalFlowOut.ToString()));

            return result;

        }

        /// <summary>
        /// 计算所选部分的流动均衡
        /// </summary>
        /// <param name="index"></param>
        /// <param name="selected"></param>
        /// <returns></returns>
        public List<FlowBudget> CalFlowBudget(int index, List<int[]> selected)
        {
            if (this._ccfData == null)
            {
                //出错
                return null;
            }

            List<FlowBudget> result = new List<FlowBudget>();

            double totalFlowIn = 0;
            double totalFlowOut = 0;

            for (int i = 0; i < this._ccfData.Count; i++)
            {
                //如果需求超出范围
                if (index >= this._ccfData[i].Datas.Count || index < 0)
                {
                    //出错了
                }


                double flowIn = 0;
                double flowOut = 0;

                if (this._ccfData[i].Id == "lpf" || this._ccfData[i].Id == "bcf")  //特殊情况的两种文件
                {
                    List<string> strs = new List<string>();

                    foreach (HA.ModFlow.Domain.DomainLayer.BudFile budfile in this._ccfData[i].Datas)
                    {
                        string str = "";
                        foreach (char c in budfile.TEXT)
                        {
                            str += c;
                        }
                        if (strs.Contains(str) == false)
                        {
                            strs.Add(str);
                        }
                    }

                    for (int j = 0; j < strs.Count; j++)
                    {
                        flowIn = 0;
                        flowOut = 0;

                        foreach (int[] ijk in selected)
                        {
                            double value = this._ccfData[i].Datas[strs.Count * index + j].Data.Datas[ijk[0]-1, ijk[1]-1, ijk[2]-1];
                            if (value > 0)
                            {
                                flowIn += value;
                            }
                            if (value < 0)
                            {
                                flowOut += value;
                            }
                        }

                        //foreach (double value in this._ccfData[i].Datas[strs.Count * index + j].Data.Datas)
                        //{
                        //    if (value > 0)
                        //    {
                        //        flowIn += value;
                        //    }
                        //    if (value < 0)
                        //    {
                        //        flowOut += value;
                        //    }
                        //}

                        totalFlowIn += flowIn;
                        totalFlowOut += flowOut;

                        string name = strs[j];
                        //foreach (char c in this._ccfData[i].Datas[this._ccfData[i].Datas.Count / strs.Count * j + index].TEXT)
                        //{
                        //    name += c;
                        //}
                        FlowBudget bud = new FlowBudget(name.Trim(), flowIn.ToString(), flowOut.ToString());
                        result.Add(bud);
                    }
                }
                else
                {

                    foreach (int[] ijk in selected)
                    {
                        double value = this._ccfData[i].Datas[index].Data.Datas[ijk[0]-1, ijk[1]-1, ijk[2]-1];
                        if (value > 0)
                        {
                            flowIn += value;
                        }
                        if (value < 0)
                        {
                            flowOut += value;
                        }
                    }

                    //foreach (double value in this._ccfData[i].Datas[index].Data.Datas)
                    //{
                    //    if (value > 0)
                    //    {
                    //        flowIn += value;
                    //    }
                    //    if (value < 0)
                    //    {
                    //        flowOut += value;
                    //    }
                    //}

                    totalFlowIn += flowIn;
                    totalFlowOut += flowOut;

                    FlowBudget bud = new FlowBudget(this._ccfData[i].Name.Trim(), flowIn.ToString(), flowOut.ToString());

                    result.Add(bud);
                }


            }

            result.Add(new FlowBudget("总流量", totalFlowIn.ToString(), totalFlowOut.ToString()));

            return result;
        }



        /// <summary>
        /// 构造向量
        /// </summary>
        public void GenerateVectors( double angle)
        //public void GenerateVectors(List<List<int[,]>> ibound, double angle)
        //public void GenerateVectors(List<int[,]> ibound, double angle)
       
        {
            List<List<int[,]>> ibound = this.TimeStepIBound;

            if (ibound != null && ibound.Count > 0)
            {
            }
            else
            { 
                return; 
            }

            DSVectorGrid3d vector3d = new DSVectorGrid3d();

            List<CellCenterVector3dDS> datas = new List<CellCenterVector3dDS>();

            List<CellCenterDataSet3d> ccfmags = new List<CellCenterDataSet3d>();

         
            
            //先判断有没有数据
            if (this._ccfData == null)
            {
                this._vectorGridData = null;
                return;
            }

            HA.ModFlow.Domain.DomainLayer.BudData budData = null;

            //查找lpf或bcf文件
            foreach (HA.ModFlow.Domain.DomainLayer.BudData bud in this._ccfData)
            {
                if (bud.Id != "lpf" && bud.Id != "bcf") continue;
                budData = bud;
            }

            //判断存不存在lpf文件或bcf文件和文件有没有数据
            if (budData == null || budData.Datas ==null || budData .Datas .Count ==0)
            {
                this._vectorGridData = null;
                return;
            } 
            
            List<string> strs = new List<string>();
            foreach (HA.ModFlow.Domain.DomainLayer.BudFile budfile in budData.Datas)
            {
                string str = "";
                foreach (char c in budfile.TEXT)
                {
                    str += c;
                }
                if (strs.Contains(str) == false)
                {
                    strs.Add(str);
                }
            }
            int n = strs.Count;  //存在几种数据
            int count = budData.Datas.Count / n;  //每种数据有多少个



            List<int[,]> tempIBound = new List<int[,]>();
            

            for (int index = 0; index < count; index++)
            {

                if (ibound.Count == count)
                {
                    tempIBound = ibound[index];
                }
                else
                {
                    tempIBound = ibound[0];
                
                }
                

                //存储同位置（index）上的三种类型的文件
                List<HA.ModFlow.Domain.DomainLayer.BudFile> buds = new List<ModFlow.Domain.DomainLayer.BudFile>();

                //从1开始,因为第0个为头文件
                for (int i = 1; i < strs.Count; i++)
                {
                    buds.Add(budData.Datas[n * index + i]);
                }

                if (buds.Count < 1)
                {
                    //没有文件,如何处理
                }
                //一共有三种类型的文件,其中每种都可能为空
                HA.ModFlow.Domain.DomainLayer.BudFile frontFile = null, rightFile = null, bottomFile = null;

                foreach (HA.ModFlow.Domain.DomainLayer.BudFile file in buds)
                {
                    string str = "";
                    foreach (char c in file.TEXT)
                    {
                        str += c;
                    }

                    if (str.Contains("FRONT"))
                    {
                        frontFile = file;
                    }
                    else if (str.Contains("RIGHT"))
                    {
                        rightFile = file;
                    }
                    else if (str.Contains("LOWER"))
                    {
                        bottomFile = file;
                    }

                }

                FlowVector[,,] vectors = new FlowVector[buds[0].NROW, buds[0].NCOL, buds[0].ILAY];

                double[,,] ccf_Mag = new double[buds[0].NROW, buds[0].NCOL, buds[0].ILAY];

                double min = double.MaxValue;
                double max = double.MinValue;

                for (int i = 0; i < buds[0].NROW; i++)
                {
                    for (int j = 0; j < buds[0].NCOL; j++)
                    {
                        for (int k = 0; k < buds[0].ILAY; k++)
                        {
                            #region


                            vectors[i, j, k] = new FlowVector();

                            if (frontFile != null)
                            {
                                if (tempIBound[k][i, j] == 0)
                                //if (ibound[k][i, j] == 0)
                                {
                                    vectors[i, j, k].vy = 0;
                                }
                                else
                                {
                                    if (i == 0)
                                    {
                                        vectors[i, j, k].vy = -frontFile.Data.Datas[i, j, k];
                                    }
                                    else
                                    {
                                        vectors[i, j, k].vy = -frontFile.Data.Datas[i, j, k] - frontFile.Data.Datas[i - 1, j, k];
                                    }
                                }
                            }
                            else
                            {
                                vectors[i, j, k].vy = 0;
                            }

                            if (rightFile != null)
                            {
                                if (tempIBound[k][i, j] == 0)
                                //if (ibound[k][i, j] == 0)
                                {
                                    vectors[i, j, k].vx = 0;
                                }
                                else
                                {
                                    if (j == 0)
                                    {
                                        vectors[i, j, k].vx = rightFile.Data.Datas[i, j, k];
                                    }
                                    else
                                    {
                                        vectors[i, j, k].vx = rightFile.Data.Datas[i, j, k] + rightFile.Data.Datas[i, j - 1, k];
                                    }
                                }
                            }
                            else
                            {
                                vectors[i, j, k].vx = 0;
                            }

                            if (bottomFile != null)
                            {
                                if (tempIBound[k][i, j] == 0)
                                //if (ibound[k][i, j] == 0)
                                {
                                    vectors[i, j, k].vz = 0;
                                }
                                {
                                    if (k == 0)
                                    {
                                        vectors[i, j, k].vz = -bottomFile.Data.Datas[i, j, k];
                                    }
                                    else
                                    {
                                        vectors[i, j, k].vz = -bottomFile.Data.Datas[i, j, k] - bottomFile.Data.Datas[i, j, k - 1];
                                    }
                                }
                            }
                            else
                            {
                                vectors[i, j, k].vz = 0;
                            }

                            ccf_Mag[i, j, k] = Math.Sqrt(vectors[i, j, k].vx * vectors[i, j, k].vx + vectors[i, j, k].vy *
                                vectors[i, j, k].vy + vectors[i, j, k].vz * vectors[i, j, k].vz);
                            if (ccf_Mag[i, j, k] < min) min = ccf_Mag[i, j, k];
                            if (ccf_Mag[i, j, k] > max) max = ccf_Mag[i, j, k];


                            #endregion
                        }
                    }
                }


                for (int i = 0; i < vectors.GetLength(0); i++)
                {
                    for (int j = 0; j < vectors.GetLength(1); j++)
                    {
                        for (int k = 0; k < vectors.GetLength(2); k++)
                        {
                            double x = vectors[i, j, k].vx;
                            double y = vectors[i, j, k].vy;
                            vectors[i, j, k].vx = x * Math.Cos(angle / 180 * Math.PI) - y * Math.Sin(angle / 180 * Math.PI);
                            vectors[i, j, k].vy = y * Math.Cos(angle / 180 * Math.PI) + x * Math.Sin(angle / 180 * Math.PI);
                        }
                    }
                }

                CellCenterVector3dDS cellVector3d = new CellCenterVector3dDS(vectors, tempIBound);
                //CellCenterVector3dDS cellVector3d = new CellCenterVector3dDS(vectors, ibound);
                cellVector3d.MinValue = min;
                cellVector3d.MaxValue = max;
                //此处添加id
               

                datas.Add(cellVector3d);

                //CCF_Mag
                CellCenterDataSet3d data3d = new CellCenterDataSet3d(ccf_Mag, tempIBound);
                //CellCenterDataSet3d data3d = new CellCenterDataSet3d(ccf_Mag, ibound);
                data3d.MinValue = min;
                data3d.MaxValue = max;              
                ccfmags.Add(data3d);

            }


            //。。。。。。。。。小李  2011.10.24
            this.SetGeneralVectorEllapseTime(datas,ccfmags,mfTimeStepLabel );
       

            //向量
           
            vector3d.ResetData(datas);             
            //需要用属性，以激活事件
            this.VectorGridData = vector3d;

            //模长
            DSGrid3d grid3d = new DSGrid3d(DataConstName.CCF_Mag, ccfmags);
            grid3d.Name = "单元间流动量(CCF_Mag)";
            this.Add(grid3d);

        }




        #endregion


        #region  内部方法

        //。。。。。。。。。。小李   2011.10.24
        /// <summary>
        ///  给CellCenterDataSet3d赋值EllapseTime数据信息
        /// </summary>
        /// <param name="mfTimeStepLabel"></param>
        private void SetCCFToDataSetEllapseTime(DSGrid3d dsgrid, List<HA.ModFlow.Domain.DomainLayer.MFTimeStepLabel> mfTimeStepLabel)
        {

            if (mfTimeStepLabel == null)
            {
                return;
            }

            if (dsgrid == null)
            {
                return;
            }
            if (dsgrid.LstValue.Count == mfTimeStepLabel.Count)
            {
                for (int i = 0; i < mfTimeStepLabel.Count; i++)
                {

                    dsgrid.LstValue[i].EllapseTime = mfTimeStepLabel[i].EllapseTime;

                    dsgrid.LstValue[i].Label = mfTimeStepLabel[i].Label;


                }



            }


        }


        private void SetGeneralVectorEllapseTime(List<CellCenterVector3dDS> datas,
            List<CellCenterDataSet3d> ccfmags,
            List<HA.ModFlow.Domain.DomainLayer.MFTimeStepLabel> mfTimeStepLabel
            )
        {
            if (datas==null ||ccfmags ==null ||mfTimeStepLabel ==null )
            {
                return;
            }
            if (datas .Count ==ccfmags .Count &&ccfmags .Count ==mfTimeStepLabel .Count )
            {

                for (int i = 0; i < mfTimeStepLabel .Count ; i++)
                {

                    datas[i].EllapseTime = mfTimeStepLabel[i].EllapseTime;
                    ccfmags[i].EllapseTime = mfTimeStepLabel[i].EllapseTime;

                    ccfmags[i].Label = mfTimeStepLabel[i].Label;
        
                }

            }

        }

        #endregion


        #region 反序体制
        [OnDeserialized ]

        public void OnDeserialized(StreamingContext context)
        {
            /// 存储modflow的结果数据等信息
            /// 注意：此类不要轻易添加删除字段属性，如果要修改，需要修改就算结果的拷贝操作，在Data2Commands 中

            if (this.mfTimeStepLabel ==null )
            {
                this.mfTimeStepLabel = new List<ModFlow.Domain.DomainLayer.MFTimeStepLabel>();
            }
            if (this._timeStepIBound==null )
            {
                this._timeStepIBound = new List<List<int[,]>>();
            }

        }
        #endregion


    }
}
